﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using GPSCrowdSource.DataStructures;
using GPSCrowdSource.Algorithms;

namespace GPSCrowdSource.UI {

  public partial class RoutePlotter : UserControl {

    private Route myRoute = null;
    private RectangleF myBounds;

    #region Private
    
    /// <summary>
    /// Lat/Lon geo position to screen values.
    /// </summary>
    private PointF GeoToScreen(GeoPosition gp) {

      float cx = (myBounds.Left + myBounds.Right)/2.0f;
      float cy = (myBounds.Top + myBounds.Bottom)/2.0f;

      float x = gp.Longitude;
      float y = gp.Latitude;
      
      float w2 = ((float)myRoutePlot.Width/2.0f);
      float h2 = ((float)myRoutePlot.Height/2.0f);

      float sx =  ((float)myRoutePlot.Width)/myBounds.Width;
      float sy =  ((float)myRoutePlot.Height)/myBounds.Height;
      
      float xp = (x-cx)*sx;
      float yp = -((y-cy)*sy);

      return new PointF(xp + w2,
                       yp - h2);
      }

    /// <summary>
    /// Draw the current route data.
    /// </summary>
    private void RenderRoute(Graphics g) {
      
      g.Clear(Color.Teal);

      if(myRoute != null) {
       
        Pen p = new Pen(Color.White);
                
        List<PointF> pts = new List<PointF>();
        for(int i=0;i<myRoute.Count;i++) {
          PointF pt = GeoToScreen(myRoute[i]);
          pts.Add(pt);

          Pen bp = new Pen(myRoute[i].Color);
          Brush bb = bp.Brush;
          g.FillEllipse(bb,pt.X-4,pt.Y-4,8,8);
          bp.Dispose();
          bb.Dispose();
          }

        g.DrawLines(p,pts.ToArray());
        p.Dispose();
        }
      
      }

    #endregion

    #region Constructor
    public RoutePlotter() {
      InitializeComponent();
      myRoutePlot.Paint+=new PaintEventHandler(myRoutePlot_Paint);
      }
        
    #endregion

    public Route Route {
      
      get {
        return myRoute;
        }

      set {
        myRoute = value;

        if(myRoute != null) {
          float l = float.MaxValue;
          float r = float.MinValue;
          float t = float.MinValue;
          float b = float.MaxValue;

          for(int i=0;i<myRoute.Count;i++) {
            GeoPosition gp = myRoute[i];
            if(gp.Longitude > r)
              r = gp.Longitude;
            if(gp.Longitude < l)
              l = gp.Longitude;
            if(gp.Latitude > t)
              t = gp.Latitude;
            if(gp.Latitude < b)
              b = gp.Latitude;
            }

          myBounds = new RectangleF(l,t,Math.Abs(r-l),Math.Abs(b-t));
          }

        Refresh();
        }
    }

    #region U/I Callbacks
    

    /// <summary>
    /// Called to paint the
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void myRoutePlot_Paint(object sender, PaintEventArgs e) {
      RenderRoute(e.Graphics);
      }

    #endregion
    }

  }
